/*
 * Galaxium Messenger
 * Copyright (C) 2007 Ben Motmans <ben.motmans@gmail.com>
 * 
 * License: GNU General Public License (GPL)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;
using System.IO;
using System.Xml;
using System.Text;
using System.Collections.Generic;

using Anculus.Core;
using Galaxium.Core;

namespace Galaxium.Protocol
{
	public static class SessionUtility
	{
		public static EventHandler<SessionEventArgs> ActiveSessionChanged;
		public static EventHandler<ContactEventArgs> SelectedContactChanged;
		public static EventHandler AddingSessionChanged;
		
		public static EventHandler<SessionEventArgs> SessionAdded;
		public static EventHandler<SessionEventArgs> SessionRemoved;

		private static ISession _activeSession;
		private static IContact _selectedContact;
		
		private static List<ISession> _sessions;
		private static bool _addingSession = true;
		
		static SessionUtility ()
		{
			_sessions = new List<ISession> ();
		}
		
		public static bool AddingSession {
			get { return _addingSession; }
			set { _addingSession = value; if(AddingSessionChanged != null) AddingSessionChanged (null, new EventArgs ()); }
		}
		
		public static int Count {
			get { return _sessions.Count; }
		}

		public static IEnumerable<ISession> Sessions
		{
			get { return _sessions; }
		}

		public static ISession ActiveSession
		{
			get { return _activeSession; }
			set {
				if (_activeSession != value) {
					_activeSession = value;

					if (ActiveSessionChanged != null)
						ActiveSessionChanged (null, new SessionEventArgs (value));
				}
			}
		}
		
		public static IContact SelectedContact
		{
			get { return _selectedContact; }
			set {
				if (_selectedContact != value) {
					_selectedContact = value;
					
					if (SelectedContactChanged != null)
						SelectedContactChanged (null, new ContactEventArgs (value));
				}
			}
		}
		
		public static void AddSession (ISession session)
		{
			ThrowUtility.ThrowIfNull ("sessions", session);

			lock (_sessions)
			{
				if (!_sessions.Contains (session))
				{
					_sessions.Add (session);
					
					if (SessionAdded != null)
						SessionAdded (null, new SessionEventArgs (session));
				}
			}
		}

		public static void RemoveSession (ISession session)
		{
			ThrowUtility.ThrowIfNull ("sessions", session);
			
			lock (_sessions)
			{
				if (_sessions.Remove (session))
				{
					if (ActiveSession == session || ActiveSession == null)
					{
						if (_sessions.Count > 0)
							ActiveSession = _sessions[0];
						else
						{
							Log.Warn ("No sessions remain. Setting to NULL active session.");
							ActiveSession = null;
						}
					}
					
					if (SessionRemoved != null)
						SessionRemoved (null, new SessionEventArgs (session));
				}
			}
		}
		
		public static ISession GetSession(string account, IProtocol protocol)
		{
			lock (_sessions)
			{
				int index = Sort.BinarySearchIndex<ISession, string> (_sessions, new SessionComparer (), account);
				
				if (_sessions[index].Account.Protocol == protocol)
					return _sessions[index];
				else
					return null;
			}
		}
		
		public static bool SessionExists (string account, IProtocol protocol)
		{
			lock (_sessions)
			{
				int index = Sort.BinarySearchIndex<ISession, string> (_sessions, new SessionComparer (), account);
				
				if (index >= 0)
					return _sessions[index].Account.Protocol == protocol;
				else return false;
			}
		}

		private class SessionComparer : IPropertyComparer<ISession, string>
		{
			public int Compare (ISession t, string u)
			{
				return t.Account.UniqueIdentifier.CompareTo (u);
			}
		}
	}
}